
`include "defines.v"

module alu (
    input  wire              rst,
    
    input  wire [`BUS_WIDTH] alu_ia,
    input  wire [`BUS_WIDTH] alu_ib,
    input  wire [3 :      0] alu_ctr,

    output reg  [`BUS_WIDTH] result,
    output reg               zero
);


    wire signed [`BUS_WIDTH] alu_ia_signed;
    wire signed [`BUS_WIDTH] alu_ib_signed;

    assign alu_ia_signed = alu_ia;
    assign alu_ib_signed = alu_ib;
    
    always @(*) begin
        if (rst) begin
            result = `ZERO_WORD;
            zero   = 1'b0;
        end
        else begin
            case (alu_ctr)
                4'b0000: begin    // add 加法运算
                    result = alu_ia + alu_ib;
                end
                4'b0001: begin    // sll 逻辑左移
                    result = alu_ia << alu_ib[5 : 0];
                end
                4'b0010: begin    // slt 带符号整数比较，小于置1
                    result = (alu_ia_signed < alu_ib_signed) ? 64'b1 : `ZERO_WORD;
                end
                4'b0011: begin    // sltu 无符号整数比较，小于置1
                    result = (alu_ia < alu_ib) ? 64'b1 : `ZERO_WORD;
                end
                4'b0100: begin    // srl 逻辑右移
                    result = alu_ia >> alu_ib[5 : 0];
                end
                4'b0101: begin    // sra 算术右移
                    result = ({64{alu_ia[63]}} << (6'b11_1111 - alu_ib[5 : 0])) | (alu_ia >> alu_ib[5 : 0]);
                end
                4'b0110: begin    // or 按位或运算
                    result = alu_ia | alu_ib;
                end
                4'b0111: begin    // xor 按位异或运算
                    result = alu_ia ^ alu_ib;
                end
                4'b1000: begin    // sub 减法运算
                    result = (alu_ia - alu_ib);
                end
                4'b1001: begin    // and 按位与运算
                    result = alu_ia & alu_ib;
                end
                4'b1010: begin    // sllw 截取低32位逻辑左移，结果零扩展
                    result = {32'b0, (alu_ia[31 : 0] << alu_ib[4 : 0])};
                end
                4'b1011: begin    // srlw 截取低32位逻辑右移，结果零扩展
                    result = {32'b0, (alu_ia[31 : 0] >> alu_ib[4 : 0])};
                end
                4'b1100: begin    // sraw 截取低32位算术右移，结果零扩展
                    result = {32'b0, ({32{alu_ia[31]}} << (5'b11111 - alu_ib[4 : 0])) | (alu_ia[31 : 0] >> alu_ib[4 : 0])};
                end
                4'b1111: begin    // srcb 选择操作数b直接输出
                    result = alu_ib;
                end
                default: begin
                    result = `ZERO_WORD;
                end
            endcase
            zero = (result == 64'b0) ? 1'b1 : 1'b0;     // 零标志
        end    
    end


endmodule
